<template>
  <div>
    <vxe-grid ref="xGrid" v-bind="gridOptions" @menu-click="onMenuClick" @header-cell-dblclick="onHeaderDblclick"></vxe-grid>
    <el-dialog :visible.sync="rename.visible" :title="'重命名：' + (rename.columnTitle || '')" width="360px" append-to-body>
      <el-form @submit.native.prevent>
        <el-form-item label="新标题">
          <el-input v-model="rename.draft" placeholder="请输入列标题" maxlength="30" show-word-limit @keyup.enter.native="onSave" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="rename.visible=false">取消</el-button>
        <el-button type="primary" @click="onSave">保存</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    const gridOptions = {
      border: true,
      showOverflow: true,
      showFooter: true,
      keepSource: true,
      mouseConfig: {
        selected: true,
      },
      keyboardConfig: {
        isAll: true,
        isClip: true,
        isEdit: true,
        isDel: true,
        isEsc: true // 是否开启Esc键关闭编辑功能
      },
      editConfig: {
        trigger: 'dblclick',
        mode: 'cell',
        showStatus: true
      },
      columns: [
        { type: 'seq', width: 70 },
        { field: 'name', title: 'Name', editRender: { name: 'input' } },
        { field: 'nickname', title: 'Nickname', editRender: { name: 'input' } },
        { field: 'age', title: 'Age', editRender: { name: 'input' } },
        { field: 'role', title: 'Role', sortable: true, editRender: { name: 'input' } },
        { field: 'address', title: 'Address', sortable: true, editRender: { name: 'input' } }
      ],
      data: [
        { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
        { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
        { id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
        { id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 23, address: 'Shenzhen' },
        { id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
      ],
      menuConfig: {
        header: {
          options: [
            [
              { code: 'COPY_TITLE', name: '复制列标题' },
              { code: 'HIDDEN_COLUMN', name: '隐藏列' },
              { code: 'CLEAR_SORT', name: '清除排序' },
              { code: 'RESET_COLUMN', name: '重置个性化列' }
            ],
            [
              {
                name: '列操作',
                children: [
                  { code: 'INSERT_COL_LEFT', name: '在左侧插入列' },
                  { code: 'INSERT_COL_RIGHT', name: '在右侧插入列' },
                  { code: 'DELETE_THIS_COLUMN', name: '删除当前列' }
                ]
              }
            ]
          ]
        },
        body: {
          options: [
            [
              { code: 'CLEAR_CELL', name: '清除值' },
              { code: 'REVERT_CELL', name: '还原值' }
            ],
            [
              {
                name: '插入单行数据',
                children: [
                  { code: 'INSERT_AT_ROW', name: '插入单行' },
                  { code: 'INSERT_NEXT_AT_ROW', name: '插入单行 next' },
                  { code: 'INSERT_AT_EDIT_ROW', name: '插入单行并编辑' },
                  { code: 'INSERT_NEXT_AT_EDIT_ROW', name: '插入单行 next 并编辑' }
                ]
              },
              {
                name: '插入多行数据',
                children: [
                  { code: 'BATCH_INSERT_AT_ROW', name: '插入多行' },
                  { code: 'BATCH_INSERT_NEXT_AT_ROW', name: '插入多行 next' },
                  { code: 'BATCH_INSERT_AT_EDIT_ROW', name: '插入多行并编辑' },
                  { code: 'BATCH_INSERT_NEXT_AT_EDIT_ROW', name: '插入多行 next 并编辑 ' }
                ]
              }
            ],
            [
              {
                name: '列操作',
                children: [
                  { code: 'INSERT_COL_LEFT', name: '在左侧插入列' },
                  { code: 'INSERT_COL_RIGHT', name: '在右侧插入列' },
                  { code: 'DELETE_THIS_COLUMN', name: '删除当前列' }
                ]
              }
            ],
            [
              {
                name: '删除数据',
                children: [
                  { code: 'DELETE_ROW', name: '删除行' },
                  { code: 'DELETE_CHECKBOX_ROW', name: '删除复选框勾选行' }
                ]
              }
            ],
            [
              {
                name: '排序',
                children: [
                  { code: 'SORT_ASC', name: '升序' },
                  { code: 'SORT_DESC', name: '倒序' },
                  { code: 'CLEAR_SORT', name: '清除当前列排序' },
                  { code: 'CLEAR_ALL_SORT', name: '清除所有列排序' }
                ]
              }
            ],
            [
              {
                name: '合并单元格',
                children: [
                  { code: 'MERGE_SAME_DOWN', name: '合并向下（同值连续）' },
                  { code: 'MERGE_INPUT', name: '手动输入合并范围' },
                  { code: 'UNMERGE_AT_CELL', name: '取消当前块合并' },
                  { code: 'CLEAR_ALL_MERGE', name: '清除全部合并' }
                ]
              }
            ]
          ]
        },
      },
      mergeCells: [],
      footerData: [{ checkbox: '合计', age: 135 }]
    };
    return {
      gridOptions,
      // 选择状态（不使用 mouseConfig.area，自定义拖拽）
      areaSelecting: false,
      areaAnchor: null,   // { ri, ci }
      areaHover: null,    // { ri, ci }
      areaActive: false,  // 是否有激活的区域
      rename: {
        visible: false,
        field: '',
        columnTitle: '',
        draft: ''
      }
    };
  },
  mounted() {
    // 让 vxe 在渲染时调用我们的 cellClassName
    this.gridOptions.cellClassName = this.cellClassName;
    // 还原已记录的合并
    const xGrid = this.$refs.xGrid;
    if (xGrid && Array.isArray(this.gridOptions.mergeCells) && this.gridOptions.mergeCells.length) {
      xGrid.setMergeCells(this.gridOptions.mergeCells);
    }
    // 绑定表体的鼠标按下（委托）
    const root = this.$refs.xGrid && this.$refs.xGrid.$el;
    if (root) {
      root.addEventListener('mousedown', this.onBodyMouseDown, true);
    }
    // ESC 清除区域
    window.addEventListener('keydown', this.onKeydown);
  },
  beforeDestroy() {
    const root = this.$refs.xGrid && this.$refs.xGrid.$el;
    if (root) root.removeEventListener('mousedown', this.onBodyMouseDown, true);
    window.removeEventListener('keydown', this.onKeydown);
    this.detachDocDrag();
  },
  methods: {
    // ===== 区域渲染：为落在矩形内的单元格加样式 =====
    cellClassName({ rowIndex, column, columnIndex }) {
      if (!this.areaActive || this.areaAnchor == null || this.areaHover == null) return '';
      // 跳过序号/类型列不高亮（可按需保留）
      if (column && column.type) return '';
      const r0 = Math.min(this.areaAnchor.ri, this.areaHover.ri);
      const r1 = Math.max(this.areaAnchor.ri, this.areaHover.ri);
      const c0 = Math.min(this.areaAnchor.ci, this.areaHover.ci);
      const c1 = Math.max(this.areaAnchor.ci, this.areaHover.ci);
      if (rowIndex >= r0 && rowIndex <= r1 && columnIndex >= c0 && columnIndex <= c1) {
        // 边框样式：判定边缘
        const edges = [];
        if (rowIndex === r0) edges.push('is-area-top');
        if (rowIndex === r1) edges.push('is-area-bottom');
        if (columnIndex === c0) edges.push('is-area-left');
        if (columnIndex === c1) edges.push('is-area-right');
        return ['is-area-selected'].concat(edges).join(' ');
      }
      return '';
    },
    // ===== 拖拽选择：mousedown -> mousemove -> mouseup =====
    onBodyMouseDown(e) {
      // 只处理左键，并且目标在表体 td
      if (e.button !== 0) return;
      const xGrid = this.$refs.xGrid;
      if (!xGrid) return;
      const cell = e.target && e.target.closest && e.target.closest('.vxe-body--column');
      if (!cell) return;

      const hit = xGrid.getCellByEvent ? xGrid.getCellByEvent(e) : null;
      if (!hit || !hit.row || !hit.column) return;

      const ri = xGrid.getRowIndex(hit.row);
      const ci = xGrid.getColumnIndex(hit.column);
      if (ri < 0 || ci < 0) return;

      this.areaSelecting = true;
      this.areaActive = true;
      this.areaAnchor = { ri, ci };
      this.areaHover = { ri, ci };

      // 禁止选中文字
      e.preventDefault();
      document.body.classList.add('area-selecting');
      // 绑定文档级 move/up
      this.attachDocDrag();
      // 触发刷新
      this.repaintArea();
    },
    onDocMouseMove(e) {
      if (!this.areaSelecting) return;
      const xGrid = this.$refs.xGrid;
      if (!xGrid) return;
      const hit = xGrid.getCellByEvent ? xGrid.getCellByEvent(e) : null;
      if (hit && hit.row && hit.column) {
        const ri = xGrid.getRowIndex(hit.row);
        const ci = xGrid.getColumnIndex(hit.column);
        if (ri >= 0 && ci >= 0) {
          this.areaHover = { ri, ci };
          this.repaintArea();
        }
      }
    },
    onDocMouseUp() {
      if (!this.areaSelecting) return;
      this.areaSelecting = false;
      document.body.classList.remove('area-selecting');
      this.detachDocDrag();
      // 保留最后一个矩形为“激活区域”，如果需要清除可按 ESC 或提供按钮
      this.repaintArea();
    },
    onKeydown(e) {
      if (e.key === 'Escape') {
        this.clearAreaSelection();
      }
    },
    clearAreaSelection() {
      this.areaSelecting = false;
      this.areaActive = false;
      this.areaAnchor = null;
      this.areaHover = null;
      document.body.classList.remove('area-selecting');
      this.detachDocDrag();
      this.repaintArea();
    },
    attachDocDrag() {
      document.addEventListener('mousemove', this.onDocMouseMove, true);
      document.addEventListener('mouseup', this.onDocMouseUp, true);
    },
    detachDocDrag() {
      document.removeEventListener('mousemove', this.onDocMouseMove, true);
      document.removeEventListener('mouseup', this.onDocMouseUp, true);
    },
    repaintArea() {
      // 让 vxe 重新计算单元格类名
      const xGrid = this.$refs.xGrid;
      if (xGrid && xGrid.refreshColumn) {
        xGrid.refreshColumn(); // 仅刷新列渲染
      } else {
        this.$forceUpdate();
      }
    },
    onMenuClick({ menu, type, row, column }) {
      if (!menu || !menu.code) return;
      if (menu.code === 'INSERT_COL_LEFT') return this.insertColumnBy(column, 'left');
      if (menu.code === 'INSERT_COL_RIGHT') return this.insertColumnBy(column, 'right');
      if (menu.code === 'DELETE_THIS_COLUMN') return this.deleteCurrentColumn(column);
      // 合并相关
      if (menu.code === 'MERGE_SAME_DOWN') return this.mergeSameDown({ row, column });
      if (menu.code === 'MERGE_INPUT') return this.mergeByInput({ row, column });
      if (menu.code === 'UNMERGE_AT_CELL') return this.unmergeAtCell({ row, column });
      if (menu.code === 'CLEAR_ALL_MERGE') return this.clearAllMerge();
    },
    insertColumnBy(column, side = 'right') {
      const rawIndex = this.findRawColumnIndex(column);
      if (rawIndex < 0) return;

      // 不允许对特殊列（checkbox/seq）左侧插入（可按需放开）
      const targetCfg = this.gridOptions.columns[rawIndex];
      if (targetCfg.type === 'checkbox' || targetCfg.type === 'seq') {
        // 放在其后
        side = 'right';
      }

      const insertIndex = side === 'left' ? rawIndex : rawIndex + 1;

      const newField = this.generateNewField();
      const newCol = {
        field: newField,
        title: `新列 ${newField}`,
        minWidth: 120,
        editRender: { name: 'input' },
        sortable: true
      };

      // 1) 插入列定义
      const cols = [...this.gridOptions.columns];
      cols.splice(insertIndex, 0, newCol);
      this.gridOptions.columns = cols;

      // 2) 给每一行补字段
      this.gridOptions.data = this.gridOptions.data.map(r => ({ ...r, [newField]: '' }));

      // 3) 刷新列（更稳妥）
      this.$nextTick(() => {
        this.$refs.xGrid?.reloadColumn(this.gridOptions.columns);
      });
    },
    deleteCurrentColumn(column) {
      const rawIndex = this.findRawColumnIndex(column);
      if (rawIndex < 0) return;

      const cfg = this.gridOptions.columns[rawIndex];
      // 保护：不删特殊列
      if (cfg.type === 'checkbox' || cfg.type === 'seq') return;

      const field = cfg.field;

      // 1) 移除列定义
      const cols = [...this.gridOptions.columns];
      cols.splice(rawIndex, 1);
      this.gridOptions.columns = cols;

      // 2) 可选：移除数据字段（或保留）
      this.gridOptions.data = this.gridOptions.data.map(r => {
        const { [field]: _, ...rest } = r;
        return rest;
      });

      this.$nextTick(() => {
        this.$refs.xGrid?.reloadColumn(this.gridOptions.columns);
      });
    },
    findRawColumnIndex(column) {
      // column.property 是字段名；column.type 是类型列标识
      const prop = column && column.property;
      const ctype = column && column.type;
      return this.gridOptions.columns.findIndex(cfg => (prop ? cfg.field === prop : ctype ? cfg.type === ctype : false));
    },
    generateNewField() {
      // 生成不重复的字段名 col_1, col_2, ...
      let i = 1;
      const exists = new Set(this.gridOptions.columns.map(c => c.field).filter(Boolean));
      while (exists.has(`col_${i}`)) i++;
      return `col_${i}`;
    },
    onHeaderDblclick (params) {
      const col = params && params.column;
      // 跳过特殊列（checkbox/seq 等）
      if (!col || col.type) return;
      const field = col.property || col.field;
      if (!field) return;
      // 当前显示标题（可能已被自定义覆盖）
      const cfg = this.gridOptions.columns.find(c => c.field === field);
      const current = cfg ? (cfg.title || '') : (col.title || '');
      this.rename.visible = true;
      this.rename.field = field;
      this.rename.columnTitle = current;
      this.rename.draft = current;
    },
    onSave(){
      const field = this.rename.field;
      if (!field) return;
      const val = (this.rename.draft || '').trim();
      const cols = this.gridOptions.columns;
      const idx = cols.findIndex(c => c.field === field);
      if (idx === -1) { this.rename.visible = false; return; }
      // 为空 = 还原默认标题
      const def = cols[idx].defaultTitle || cols[idx].title || '';
      cols[idx].title = val ? val : def;
      this.rename.visible = false;
      // 刷新列配置
      this.$nextTick(() => {
        this.$refs.xGrid && this.$refs.xGrid.reloadColumn(this.gridOptions.columns);
      });
    }
  }
};
</script>
<style lang="scss" scoped>
/* 区域选中样式 */
:deep(.vxe-body--column.is-area-selected) {
  background-color: rgba(64, 158, 255, 0.15) !important;
}
:deep(.vxe-body--column.is-area-top)    { box-shadow: inset 0 2px 0 0 #409eff; }
:deep(.vxe-body--column.is-area-bottom) { box-shadow: inset 0 -2px 0 0 #409eff; }
:deep(.vxe-body--column.is-area-left)   { box-shadow: inset 2px 0 0 0 #409eff; }
:deep(.vxe-body--column.is-area-right)  { box-shadow: inset -2px 0 0 0 #409eff; }
/* 拖拽时禁止选中文本 */
:deep(.area-selecting), :deep(.area-selecting *) {
  user-select: none !important;
}
</style>
